package org.marverse.serialization

import scala.collection.mutable.{HashMap, Buffer, ArrayBuffer}

class ClassRegistry {
  type ID = Int
  protected val instantiaters = HashMap[ID, Instantiater[_]]()
  protected val deserializers = HashMap[ID, Deserializer[_]]()
  protected val instanceSerializers = HashMap[Class[_], (ID, InstanceSerializer[_])]()
  protected val serializers = HashMap[Class[_], Buffer[(ID, Serializer[_])]]()
                                  
  def registerInstantiater(id: ID, inst: Instantiater[_]) {
    if (instantiaters contains id)
      throw new RuntimeException()
    instantiaters(id) = inst
  }
  
  def registerDeserializer(id: ID, des: Deserializer[_]) {
    if (deserializers contains id)
      throw new RuntimeException()
    deserializers(id) = des
  }
  
  def registerInstanceSerializer[T <: AnyRef](clazz: Class[T], id: ID, instSer: InstanceSerializer[T]) {
    if (instanceSerializers contains clazz)
      throw new RuntimeException()
    instanceSerializers(clazz) = (id, instSer)
  }
  
  def registerSerializer[T <: AnyRef](clazz: Class[T], id: ID, ser: Serializer[T]) {
    serializers.getOrElseUpdate(clazz, new ArrayBuffer()) += (id, ser)  
  }
  
  def register[T <: AnyRef](s11n: S11nInfo*) {
    for (s <- s11n) {
	  val classes = s.classes
	  val ids = s.ids
	  val maxID = (ids :\ Int.MinValue)(Math.max)
	    
	  if (s.isInstanceOf[Instantiater[_]])
	    for (id <- ids)
	      registerInstantiater(id, s.asInstanceOf[Instantiater[T]])
	  if (s.isInstanceOf[InstanceSerializer[_]])
	    for (clazz <- classes)
	      registerInstanceSerializer[T](clazz.asInstanceOf[Class[T]], maxID, s.asInstanceOf[InstanceSerializer[T]])
	  if (s.isInstanceOf[Deserializer[_]])
	    for (id <- ids)
	      registerDeserializer(id, s.asInstanceOf[Deserializer[T]])
	  if (s.isInstanceOf[Serializer[_]])
	    for (clazz <- classes)
	      registerSerializer[T](clazz.asInstanceOf[Class[T]], maxID, s.asInstanceOf[Serializer[T]])
	}
  }
  
  def getInstantiater(id: ID) = instantiaters(id)
  def getDeserializer(id: ID) = deserializers(id)
  def getInstanceSerializer(clazz: Class[_]) = instanceSerializers(clazz)
  def getSerializers(clazz: Class[_]) = serializers.getOrElse(clazz, Seq.empty)
}
